package com.example.kotlindemo

/**
 * @author Lmy
 * @功能:
 * @Creat 2020/5/14 17:25
 * @Compony 永远相信美好的事物即将发生
 */
/*主构造函数至少包含一个参数。

所有的主构造函数的参数必须标识为val 或者 var ;

数据类不可以声明为 abstract, open, sealed 或者 inner;

数据类不能继承其他类 (但是可以实现接口)。*/
data class DataClass(val name: String) {
}

//fun main() {
//    val jack = DataClass(name = "Jack")
//    val olderJack = jack.copy(name = "哈哈哈")
//    // 使用 copy 类复制 DataClass 数据类，并修改 name 属性:
//
//
//    println(jack)
//    println(olderJack)
//    var boxInt = Box<Int>(10)
//    var boxString = Box<String>("Runoob")
//
//    println(boxInt.value)
//    println(boxString.value)
//    doPrint("hahahah")
//    doPrint(10)
//    doPrint(10.92f)
//    sort(listOf(1, 2, 3)) // OK。Int 是 Comparable<Int> 的子类型
//    sort(listOf("111", "222", "22")) // OK。Int 是 Comparable<Int> 的子类型
//
//
//}

/**
 * 泛型的约束
 * 默认的泛型约束上界为Any 超类
 *
 */
fun <T : Comparable<T>> sort(list: List<T>) {
    // ……
}


class Box<T>(t: T) {
    var value = t
}

/**
 * 使用泛型来定义参数
 *
 */
fun <T> doPrint(content: T) {

    when (content) {
        is String -> print("这是一个String的参数$content")
        is Int -> print("这是一个Int的参数$content")
        else -> print("未知的参数")

    }
}


class User<out T> {
    //此处不能用var，否则就有setter方法
    //setter方法会导致T出现在方法形参中
    val info: T

    constructor(info: T) {
        this.info = info
    }

    fun test(): T {
        println("执行test方法")
        return info
    }
}

class Item<in T> {
    fun foo(t: T) {
        println(t)
    }
}

fun main(args: Array<String>) {
    //此时T的类型是String
    var user = User<String>("Kotlin")
    println(user.info)
    //对于u2而言，它的类型是User<Any>,此时T的类型是Any
    //由于程序声明了T支持协变，因此User<String>可当成User<Any>使用
    var u2: User<Any> = user
    println(u2.info)


    //此时T的类型是Any
    var item = Item<Any>()
    item.foo(20)
    var im2: Item<String> = item
    //im2的实际类型是Item<Any>,因此它的参数只要是Any即可
    //声明了im2的类型为Item<String>
    //因此传入的参数只可能是String
    im2.foo("Kotlin")

    val res = MyClsEx<Int, String>(17, "shhssh")
    println("${res.a}+b refering to ahead")
    res.MyFun("哈哈哈哈\n")


    var color: Color = Color.BLUE

    println(Color.values())
    println(Color.valueOf("RED"))
    println(color.name)
    println(color.ordinal)
}

interface MyIfe<out C, in D> {
    fun MyFun(d: D) {
        println(d)
    }

}

class MyClsEx<out A, in B>(val a: A, b: B) : MyIfe<Any, Any> {
    init {
        println(b)
    }

    fun foo(): A {
        return a
    }
}


/**
 * 枚举类的使用
 * 可以在开始使用的时候进行初始化
 *
 */
enum class Color(value: Int) {

    RED(10), BLACK(10), BLUE(10), GREEN(10), WHITE(10),


}


class G {
    // 私有函数，所以其返回类型是匿名对象类型
    private fun foo() = object {
        val x: String = "x"
    }

    /**
     * 如果你使用匿名对象作为公有函数的 返回类型或者用作公有属性的类型，
     * 那么该函数或属性的实际类型 会是匿名对象声明的超类型，
     * 如果你没有声明任何超类型，就会是 Any。在匿名对象 中添加的成员将无法访问。
     *
     */
    // 公有函数，所以其返回类型是 Any
    fun publicFoo() = object {
        val x: String = "x"
    }

    fun bar() {
        val x1 = foo().x        // 没问题
//        val x2 = publicFoo().x  // 错误：未能解析的引用“x”
    }
}
